package type;

import org.junit.Test;

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;
import java.util.Map;

/**
 * Created by E440 on 2017/4/13.
 */
public class GenericTest<T1,T2 extends Number> {
    private Map<T1 , Integer> map = null;

    @Test
    public  void testParameterizedType() throws NoSuchFieldException, SecurityException{

        Type mapGenericType = GenericTest.class.getDeclaredField("map").getGenericType();  //ParameterizedType
        if(mapGenericType instanceof ParameterizedType){
            Type basicType = ((ParameterizedType) mapGenericType).getRawType();
            ParameterizedType parameterizedType=((ParameterizedType) mapGenericType);


            System.out.println("basicType equals Map.class is " + (basicType ==Map.class)); //返回True

            System.out.println("基本类型为："+basicType);  //Map
            System.out.println("mapGenericType=" + parameterizedType);
            // 获取泛型类型的泛型参数, 分别为
            Type[] types = ((ParameterizedType) mapGenericType).getActualTypeArguments();
            for (int i = 0; i < types.length; i++) {
                System.out.println("第"+(i+1)+"个泛型类型是："+types[i]);
            }
            //返回为 T1, class java.lang.Integer

            System.out.println(((ParameterizedType) mapGenericType).getOwnerType());  //null
        }
    }

    //private Map<T1 , Integer> map = null;
    @Test
    public  void testTypeVariable() throws NoSuchFieldException, SecurityException{
        Type mapGenericType = GenericTest.class.getDeclaredField("map").getGenericType();  //ParameterizedType
        if(mapGenericType instanceof ParameterizedType){
            // 获取泛型类型的泛型参数, 分别为 T1, class java.lang.Integer
            Type[] types = ((ParameterizedType) mapGenericType).getActualTypeArguments();
            for (int i = 0; i < types.length; i++) {
                if( types[i] instanceof TypeVariable){
                    // T1 is TypeVariable, and Integer is not.
                    System.out.println("the "+(i+1)+"th is TypeVariable");
                }else{
                    System.out.println("the "+(i+1)+"th is not TypeVariable");
                }
                System.out.println((i + 1) + "th's type is " + types[i]);

            }

        }

        System.out.println("GenericTest TypeVariable");

        TypeVariable<Class<GenericTest>>[] typeVariables = GenericTest.class.getTypeParameters();

        // console print  T1, T2
        for(TypeVariable tmp : typeVariables){
            System.out.println(""+tmp);

            System.out.println(tmp.getGenericDeclaration());



            Type[] bounds = tmp.getBounds(); //return upper bounds
            if(bounds.length > 0){
                //T2 has upper bounds which is class java.lang.Number,
                //T1's upper bounds is Object which is default.
                System.out.println("bounds[0] is: "+bounds[0]);
            }

            System.out.println("name is: "+tmp.getName());  //  T1, T2
            System.out.println("GenericDeclaration is equals GenericTest.class: "+ (tmp.getGenericDeclaration()==GenericTest.class)); //GenericTest
        }
    }
}
